
#include "../UnitTestSystemCode/cpptest.h"
#include "../MathCode/Math.h"


class TSVector4 : public Test::Suite
{
public:
	TSVector4 ()
	{
		TEST_ADD(TSVector4::TestComparisonOp);
		TEST_ADD(TSVector4::TestEqualityOp);
		TEST_ADD(TSVector4::TestCtor);
		TEST_ADD(TSVector4::TestSum);
		TEST_ADD(TSVector4::TestDiff);
		TEST_ADD(TSVector4::TestMultByScalar);
		TEST_ADD(TSVector4::TestCrossProduct);
		TEST_ADD(TSVector4::TestDotProduct);
		TEST_ADD(TSVector4::TestNormalization);
		TEST_ADD(TSVector4::TestLength);
		TEST_ADD(TSVector4::TestLengthSq);
		TEST_ADD(TSVector4::TestTransform);
	}

	//~TSVector4 ();

protected:
    //virtual void setup ();
    //virtual void tear_down ();

private:
	void TestCtor ();
	void TestComparisonOp ();
	void TestEqualityOp ();

	void TestSum ();
	void TestDiff ();
	void TestMultByScalar ();
	void TestCrossProduct ();
	void TestDotProduct ();
	void TestNormalization ();
	void TestLength ();
	void TestLengthSq ();
	void TestTransform ();
};


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Implementation

void TSVector4::TestCtor ()
{
	Vector4 v(5,6,7,8);

	v.ctor();
	ASSERT(v.x == 0 && v.y == 0 && v.z == 0 && v.w == 1); 
}

void TSVector4::TestComparisonOp ()
{
	Vector4 v1(5,6,7,8), v2(1,2,3,4), v3(5,6,7,8);

	ASSERT(v1 == v3);
	ASSERT(v1 != v2);
}

void TSVector4::TestEqualityOp ()
{
	Vector4 v1(5,6,7,8), v2;

	v2 = v1;
	ASSERT(v1 == v2);
}

void TSVector4::TestSum ()
{
	Vector4 v1(1,2,3,2);
	Vector4 v2(5,6,7,3);
	
	// testing operator
	Vector4 v3 = v1 + v2;
	ASSERT(v3.x == 6 && v3.y == 8 && v3.z == 10);
	ASSERT(v3.w == 1);	//default ctor on v3 should have set the w to 1

	// testing method
	v3 = v1;
	v3.AddVector(v2);
	
	ASSERT(v3.x == 6 && v3.y == 8 && v3.z == 10);
	ASSERT(v3.w == 2);	//as it was set to 2
}

void TSVector4::TestDiff ()
{
	Vector4 v1(1,2,3,2);
	Vector4 v2(5,6,7,3);

	// testing operator
	Vector4 v3 = v2 - v1;
	ASSERT(v3.x == 4 && v3.y == 4 && v3.z == 4);
	ASSERT(v3.w == 1);	//default ctor on v3 should have set the w to 1

	// testing method
	v3 = v2;
	v3.SubVector(v1);
	
	ASSERT(v3.x == 4 && v3.y == 4 && v3.z == 4);
	ASSERT(v3.w == 3);	//as it was set to 3
}

void TSVector4::TestMultByScalar ()
{
	float scalar = 3.0f;

	// operator
	Vector4 v1(1,2,3,2);
	v1 *= scalar;
	ASSERT(v1.x == 3.0 && v1.y == 6.0 && v1.z == 9.0);
	ASSERT(v1.w = 2);
	
	// method
	Vector4 v2(1,2,3,2);
	v2 *= scalar;
	ASSERT(v2.x == 3.0 && v2.y == 6.0 && v2.z == 9.0);
	ASSERT(v2.w = 2);
}

void TSVector4::TestCrossProduct ()
{
	Vector4 v1(1,2,3,10);
	Vector4 v2(4,5,6,10);
	
	// method
	Vector4 v = v1.CrossProduct(v2);
	ASSERT(v.x == -3 && v.y == 6 && v.z == -3);
	ASSERT(v.w == 1);

	// operators
	v.ctor();
	v = v1;
	v ^= v2;
	ASSERT(v.x == -3 && v.y == 6 && v.z == -3);
	ASSERT(v.w == 1);

	v.ctor();
	v = v1 ^ v2;
	ASSERT(v.x == -3 && v.y == 6 && v.z == -3);
	ASSERT(v.w == 1);
}

void TSVector4::TestDotProduct ()
{
	Vector4 v1(1,2,3,10);
	Vector4 v2(4,5,6,10);
	float res = 0;

	// method
	res = v1.DotProduct(v2);
	ASSERT(res == (4*1 + 5*2 + 6*3));

	// operators
	res = v1 * v2;
	ASSERT(res == (4*1 + 5*2 + 6*3));
}

void TSVector4::TestNormalization ()
{
	Vector4 v(3,4,5,2);

	v.Normalize();
	float invQ = 1.0f / sqrt((float)3*3 + 4*4 + 5*5);
	ASSERT_DELTA(v.x, 3*invQ, EQUAT_DELTA);
	ASSERT_DELTA(v.y, 4*invQ, EQUAT_DELTA);
	ASSERT_DELTA(v.z, 5*invQ, EQUAT_DELTA);
	ASSERT(v.w == 2);
}

void TSVector4::TestLength ()
{
	Vector4 v(3,4,5,2);
	float res = 0;
	
	res = v.Length();
	ASSERT_DELTA(res, sqrt(3.0*3.0 + 4.0*4.0 + 5.0*5.0), EQUAT_DELTA);
}

void TSVector4::TestLengthSq ()
{
	Vector4 v(3,4,5,2);
	float res = 0;
	
	res = v.LengthSq();
	ASSERT_DELTA(res, 3*3 + 4*4 + 5*5, EQUAT_DELTA);
}

void TSVector4::TestTransform ()
{
	// TODO
}
